
// <copyright file="ExtendedWebBrowser.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   An extended version of the  control.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Windows.Forms
{
    using System;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Windows.Forms;

    using SubhadraSolutions.Sharp.Utils.Validation;

    /// <summary>
    ///     An extended version of the <see cref="WebBrowser" /> control.
    /// </summary>
    public class ExtendedWebBrowser : WebBrowser
    {
        #region Fields

        /// <summary>
        /// The ax i web browser 2.
        /// </summary>
        private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2;

        /// <summary>
        /// The cookie.
        /// </summary>
        private AxHost.ConnectionPointCookie cookie;

        /// <summary>
        /// The events.
        /// </summary>
        private WebBrowserExtendedEvents events;

        #endregion Fields

        #region Public Events

        /// <summary>
        ///     Fires when downloading is completed
        /// </summary>
        /// <remarks>
        ///     Here you could start monitoring for script errors.
        /// </remarks>
        public event EventHandler DownloadComplete;

        /// <summary>
        ///     Fires when downloading of a document begins
        /// </summary>
        public event EventHandler Downloading;

        /// <summary>
        ///     Raised when the browser application quits
        /// </summary>
        /// <remarks>
        ///     Do not confuse this with DWebBrowserEvents2.Quit... That's something else.
        /// </remarks>
        public event EventHandler Quit;

        /// <summary>
        ///     Fires before navigation occurs in the given object (on either a window or frameset element).
        /// </summary>
        public event EventHandler<BrowserExtendedNavigatingEventArgs> StartNavigate;

        /// <summary>
        ///     Raised when a new window is to be created. Extends DWebBrowserEvents2::NewWindow2 with additional information about
        ///     the new window.
        /// </summary>
        public event EventHandler<BrowserExtendedNavigatingEventArgs> StartNewWindow;

        #endregion Public Events

        #region Enums

        /// <summary>
        ///     A list of all the available window messages
        /// </summary>
        private enum WindowsMessages
        {
            /// <summary>
            /// The w m_ activate.
            /// </summary>
            WM_ACTIVATE = 0x6, 

            /// <summary>
            /// The w m_ activateapp.
            /// </summary>
            WM_ACTIVATEAPP = 0x1C, 

            /// <summary>
            /// The w m_ afxfirst.
            /// </summary>
            WM_AFXFIRST = 0x360, 

            /// <summary>
            /// The w m_ afxlast.
            /// </summary>
            WM_AFXLAST = 0x37F, 

            /// <summary>
            /// The w m_ app.
            /// </summary>
            WM_APP = 0x8000, 

            /// <summary>
            /// The w m_ askcbformatname.
            /// </summary>
            WM_ASKCBFORMATNAME = 0x30C, 

            /// <summary>
            /// The w m_ canceljournal.
            /// </summary>
            WM_CANCELJOURNAL = 0x4B, 

            /// <summary>
            /// The w m_ cancelmode.
            /// </summary>
            WM_CANCELMODE = 0x1F, 

            /// <summary>
            /// The w m_ capturechanged.
            /// </summary>
            WM_CAPTURECHANGED = 0x215, 

            /// <summary>
            /// The w m_ changecbchain.
            /// </summary>
            WM_CHANGECBCHAIN = 0x30D, 

            /// <summary>
            /// The w m_ char.
            /// </summary>
            WM_CHAR = 0x102, 

            /// <summary>
            /// The w m_ chartoitem.
            /// </summary>
            WM_CHARTOITEM = 0x2F, 

            /// <summary>
            /// The w m_ childactivate.
            /// </summary>
            WM_CHILDACTIVATE = 0x22, 

            /// <summary>
            /// The w m_ clear.
            /// </summary>
            WM_CLEAR = 0x303, 

            /// <summary>
            /// The w m_ close.
            /// </summary>
            WM_CLOSE = 0x10, 

            /// <summary>
            /// The w m_ command.
            /// </summary>
            WM_COMMAND = 0x111, 

            /// <summary>
            /// The w m_ compacting.
            /// </summary>
            WM_COMPACTING = 0x41, 

            /// <summary>
            /// The w m_ compareitem.
            /// </summary>
            WM_COMPAREITEM = 0x39, 

            /// <summary>
            /// The w m_ contextmenu.
            /// </summary>
            WM_CONTEXTMENU = 0x7B, 

            /// <summary>
            /// The w m_ copy.
            /// </summary>
            WM_COPY = 0x301, 

            /// <summary>
            /// The w m_ copydata.
            /// </summary>
            WM_COPYDATA = 0x4A, 

            /// <summary>
            /// The w m_ create.
            /// </summary>
            WM_CREATE = 0x1, 

            /// <summary>
            /// The w m_ ctlcolorbtn.
            /// </summary>
            WM_CTLCOLORBTN = 0x135, 

            /// <summary>
            /// The w m_ ctlcolordlg.
            /// </summary>
            WM_CTLCOLORDLG = 0x136, 

            /// <summary>
            /// The w m_ ctlcoloredit.
            /// </summary>
            WM_CTLCOLOREDIT = 0x133, 

            /// <summary>
            /// The w m_ ctlcolorlistbox.
            /// </summary>
            WM_CTLCOLORLISTBOX = 0x134, 

            /// <summary>
            /// The w m_ ctlcolormsgbox.
            /// </summary>
            WM_CTLCOLORMSGBOX = 0x132, 

            /// <summary>
            /// The w m_ ctlcolorscrollbar.
            /// </summary>
            WM_CTLCOLORSCROLLBAR = 0x137, 

            /// <summary>
            /// The w m_ ctlcolorstatic.
            /// </summary>
            WM_CTLCOLORSTATIC = 0x138, 

            /// <summary>
            /// The w m_ cut.
            /// </summary>
            WM_CUT = 0x300, 

            /// <summary>
            /// The w m_ deadchar.
            /// </summary>
            WM_DEADCHAR = 0x103, 

            /// <summary>
            /// The w m_ deleteitem.
            /// </summary>
            WM_DELETEITEM = 0x2D, 

            /// <summary>
            /// The w m_ destroy.
            /// </summary>
            WM_DESTROY = 0x2, 

            /// <summary>
            /// The w m_ destroyclipboard.
            /// </summary>
            WM_DESTROYCLIPBOARD = 0x307, 

            /// <summary>
            /// The w m_ devicechange.
            /// </summary>
            WM_DEVICECHANGE = 0x219, 

            /// <summary>
            /// The w m_ devmodechange.
            /// </summary>
            WM_DEVMODECHANGE = 0x1B, 

            /// <summary>
            /// The w m_ displaychange.
            /// </summary>
            WM_DISPLAYCHANGE = 0x7E, 

            /// <summary>
            /// The w m_ drawclipboard.
            /// </summary>
            WM_DRAWCLIPBOARD = 0x308, 

            /// <summary>
            /// The w m_ drawitem.
            /// </summary>
            WM_DRAWITEM = 0x2B, 

            /// <summary>
            /// The w m_ dropfiles.
            /// </summary>
            WM_DROPFILES = 0x233, 

            /// <summary>
            /// The w m_ enable.
            /// </summary>
            WM_ENABLE = 0xA, 

            /// <summary>
            /// The w m_ endsession.
            /// </summary>
            WM_ENDSESSION = 0x16, 

            /// <summary>
            /// The w m_ enteridle.
            /// </summary>
            WM_ENTERIDLE = 0x121, 

            /// <summary>
            /// The w m_ entermenuloop.
            /// </summary>
            WM_ENTERMENULOOP = 0x211, 

            /// <summary>
            /// The w m_ entersizemove.
            /// </summary>
            WM_ENTERSIZEMOVE = 0x231, 

            /// <summary>
            /// The w m_ erasebkgnd.
            /// </summary>
            WM_ERASEBKGND = 0x14, 

            /// <summary>
            /// The w m_ exitmenuloop.
            /// </summary>
            WM_EXITMENULOOP = 0x212, 

            /// <summary>
            /// The w m_ exitsizemove.
            /// </summary>
            WM_EXITSIZEMOVE = 0x232, 

            /// <summary>
            /// The w m_ fontchange.
            /// </summary>
            WM_FONTCHANGE = 0x1D, 

            /// <summary>
            /// The w m_ getdlgcode.
            /// </summary>
            WM_GETDLGCODE = 0x87, 

            /// <summary>
            /// The w m_ getfont.
            /// </summary>
            WM_GETFONT = 0x31, 

            /// <summary>
            /// The w m_ gethotkey.
            /// </summary>
            WM_GETHOTKEY = 0x33, 

            /// <summary>
            /// The w m_ geticon.
            /// </summary>
            WM_GETICON = 0x7F, 

            /// <summary>
            /// The w m_ getminmaxinfo.
            /// </summary>
            WM_GETMINMAXINFO = 0x24, 

            /// <summary>
            /// The w m_ getobject.
            /// </summary>
            WM_GETOBJECT = 0x3D, 

            /// <summary>
            /// The w m_ gettext.
            /// </summary>
            WM_GETTEXT = 0xD, 

            /// <summary>
            /// The w m_ gettextlength.
            /// </summary>
            WM_GETTEXTLENGTH = 0xE, 

            /// <summary>
            /// The w m_ handheldfirst.
            /// </summary>
            WM_HANDHELDFIRST = 0x358, 

            /// <summary>
            /// The w m_ handheldlast.
            /// </summary>
            WM_HANDHELDLAST = 0x35F, 

            /// <summary>
            /// The w m_ help.
            /// </summary>
            WM_HELP = 0x53, 

            /// <summary>
            /// The w m_ hotkey.
            /// </summary>
            WM_HOTKEY = 0x312, 

            /// <summary>
            /// The w m_ hscroll.
            /// </summary>
            WM_HSCROLL = 0x114, 

            /// <summary>
            /// The w m_ hscrollclipboard.
            /// </summary>
            WM_HSCROLLCLIPBOARD = 0x30E, 

            /// <summary>
            /// The w m_ iconerasebkgnd.
            /// </summary>
            WM_ICONERASEBKGND = 0x27, 

            /// <summary>
            /// The w m_ im e_ char.
            /// </summary>
            WM_IME_CHAR = 0x286, 

            /// <summary>
            /// The w m_ im e_ composition.
            /// </summary>
            WM_IME_COMPOSITION = 0x10F, 

            /// <summary>
            /// The w m_ im e_ compositionfull.
            /// </summary>
            WM_IME_COMPOSITIONFULL = 0x284, 

            /// <summary>
            /// The w m_ im e_ control.
            /// </summary>
            WM_IME_CONTROL = 0x283, 

            /// <summary>
            /// The w m_ im e_ endcomposition.
            /// </summary>
            WM_IME_ENDCOMPOSITION = 0x10E, 

            /// <summary>
            /// The w m_ im e_ keydown.
            /// </summary>
            WM_IME_KEYDOWN = 0x290, 

            /// <summary>
            /// The w m_ im e_ keylast.
            /// </summary>
            WM_IME_KEYLAST = 0x10F, 

            /// <summary>
            /// The w m_ im e_ keyup.
            /// </summary>
            WM_IME_KEYUP = 0x291, 

            /// <summary>
            /// The w m_ im e_ notify.
            /// </summary>
            WM_IME_NOTIFY = 0x282, 

            /// <summary>
            /// The w m_ im e_ request.
            /// </summary>
            WM_IME_REQUEST = 0x288, 

            /// <summary>
            /// The w m_ im e_ select.
            /// </summary>
            WM_IME_SELECT = 0x285, 

            /// <summary>
            /// The w m_ im e_ setcontext.
            /// </summary>
            WM_IME_SETCONTEXT = 0x281, 

            /// <summary>
            /// The w m_ im e_ startcomposition.
            /// </summary>
            WM_IME_STARTCOMPOSITION = 0x10D, 

            /// <summary>
            /// The w m_ initdialog.
            /// </summary>
            WM_INITDIALOG = 0x110, 

            /// <summary>
            /// The w m_ initmenu.
            /// </summary>
            WM_INITMENU = 0x116, 

            /// <summary>
            /// The w m_ initmenupopup.
            /// </summary>
            WM_INITMENUPOPUP = 0x117, 

            /// <summary>
            /// The w m_ inputlangchange.
            /// </summary>
            WM_INPUTLANGCHANGE = 0x51, 

            /// <summary>
            /// The w m_ inputlangchangerequest.
            /// </summary>
            WM_INPUTLANGCHANGEREQUEST = 0x50, 

            /// <summary>
            /// The w m_ keydown.
            /// </summary>
            WM_KEYDOWN = 0x100, 

            /// <summary>
            /// The w m_ keyfirst.
            /// </summary>
            WM_KEYFIRST = 0x100, 

            /// <summary>
            /// The w m_ keylast.
            /// </summary>
            WM_KEYLAST = 0x108, 

            /// <summary>
            /// The w m_ keyup.
            /// </summary>
            WM_KEYUP = 0x101, 

            /// <summary>
            /// The w m_ killfocus.
            /// </summary>
            WM_KILLFOCUS = 0x8, 

            /// <summary>
            /// The w m_ lbuttondblclk.
            /// </summary>
            WM_LBUTTONDBLCLK = 0x203, 

            /// <summary>
            /// The w m_ lbuttondown.
            /// </summary>
            WM_LBUTTONDOWN = 0x201, 

            /// <summary>
            /// The w m_ lbuttonup.
            /// </summary>
            WM_LBUTTONUP = 0x202, 

            /// <summary>
            /// The w m_ mbuttondblclk.
            /// </summary>
            WM_MBUTTONDBLCLK = 0x209, 

            /// <summary>
            /// The w m_ mbuttondown.
            /// </summary>
            WM_MBUTTONDOWN = 0x207, 

            /// <summary>
            /// The w m_ mbuttonup.
            /// </summary>
            WM_MBUTTONUP = 0x208, 

            /// <summary>
            /// The w m_ mdiactivate.
            /// </summary>
            WM_MDIACTIVATE = 0x222, 

            /// <summary>
            /// The w m_ mdicascade.
            /// </summary>
            WM_MDICASCADE = 0x227, 

            /// <summary>
            /// The w m_ mdicreate.
            /// </summary>
            WM_MDICREATE = 0x220, 

            /// <summary>
            /// The w m_ mdidestroy.
            /// </summary>
            WM_MDIDESTROY = 0x221, 

            /// <summary>
            /// The w m_ mdigetactive.
            /// </summary>
            WM_MDIGETACTIVE = 0x229, 

            /// <summary>
            /// The w m_ mdiiconarrange.
            /// </summary>
            WM_MDIICONARRANGE = 0x228, 

            /// <summary>
            /// The w m_ mdimaximize.
            /// </summary>
            WM_MDIMAXIMIZE = 0x225, 

            /// <summary>
            /// The w m_ mdinext.
            /// </summary>
            WM_MDINEXT = 0x224, 

            /// <summary>
            /// The w m_ mdirefreshmenu.
            /// </summary>
            WM_MDIREFRESHMENU = 0x234, 

            /// <summary>
            /// The w m_ mdirestore.
            /// </summary>
            WM_MDIRESTORE = 0x223, 

            /// <summary>
            /// The w m_ mdisetmenu.
            /// </summary>
            WM_MDISETMENU = 0x230, 

            /// <summary>
            /// The w m_ mditile.
            /// </summary>
            WM_MDITILE = 0x226, 

            /// <summary>
            /// The w m_ measureitem.
            /// </summary>
            WM_MEASUREITEM = 0x2C, 

            /// <summary>
            /// The w m_ menuchar.
            /// </summary>
            WM_MENUCHAR = 0x120, 

            /// <summary>
            /// The w m_ menucommand.
            /// </summary>
            WM_MENUCOMMAND = 0x126, 

            /// <summary>
            /// The w m_ menudrag.
            /// </summary>
            WM_MENUDRAG = 0x123, 

            /// <summary>
            /// The w m_ menugetobject.
            /// </summary>
            WM_MENUGETOBJECT = 0x124, 

            /// <summary>
            /// The w m_ menurbuttonup.
            /// </summary>
            WM_MENURBUTTONUP = 0x122, 

            /// <summary>
            /// The w m_ menuselect.
            /// </summary>
            WM_MENUSELECT = 0x11F, 

            /// <summary>
            /// The w m_ mouseactivate.
            /// </summary>
            WM_MOUSEACTIVATE = 0x21, 

            /// <summary>
            /// The w m_ mousefirst.
            /// </summary>
            WM_MOUSEFIRST = 0x200, 

            /// <summary>
            /// The w m_ mousehover.
            /// </summary>
            WM_MOUSEHOVER = 0x2A1, 

            /// <summary>
            /// The w m_ mouselast.
            /// </summary>
            WM_MOUSELAST = 0x20A, 

            /// <summary>
            /// The w m_ mouseleave.
            /// </summary>
            WM_MOUSELEAVE = 0x2A3, 

            /// <summary>
            /// The w m_ mousemove.
            /// </summary>
            WM_MOUSEMOVE = 0x200, 

            /// <summary>
            /// The w m_ mousewheel.
            /// </summary>
            WM_MOUSEWHEEL = 0x20A, 

            /// <summary>
            /// The w m_ move.
            /// </summary>
            WM_MOVE = 0x3, 

            /// <summary>
            /// The w m_ moving.
            /// </summary>
            WM_MOVING = 0x216, 

            /// <summary>
            /// The w m_ ncactivate.
            /// </summary>
            WM_NCACTIVATE = 0x86, 

            /// <summary>
            /// The w m_ nccalcsize.
            /// </summary>
            WM_NCCALCSIZE = 0x83, 

            /// <summary>
            /// The w m_ nccreate.
            /// </summary>
            WM_NCCREATE = 0x81, 

            /// <summary>
            /// The w m_ ncdestroy.
            /// </summary>
            WM_NCDESTROY = 0x82, 

            /// <summary>
            /// The w m_ nchittest.
            /// </summary>
            WM_NCHITTEST = 0x84, 

            /// <summary>
            /// The w m_ nclbuttondblclk.
            /// </summary>
            WM_NCLBUTTONDBLCLK = 0xA3, 

            /// <summary>
            /// The w m_ nclbuttondown.
            /// </summary>
            WM_NCLBUTTONDOWN = 0xA1, 

            /// <summary>
            /// The w m_ nclbuttonup.
            /// </summary>
            WM_NCLBUTTONUP = 0xA2, 

            /// <summary>
            /// The w m_ ncmbuttondblclk.
            /// </summary>
            WM_NCMBUTTONDBLCLK = 0xA9, 

            /// <summary>
            /// The w m_ ncmbuttondown.
            /// </summary>
            WM_NCMBUTTONDOWN = 0xA7, 

            /// <summary>
            /// The w m_ ncmbuttonup.
            /// </summary>
            WM_NCMBUTTONUP = 0xA8, 

            /// <summary>
            /// The w m_ ncmousehover.
            /// </summary>
            WM_NCMOUSEHOVER = 0x2A0, 

            /// <summary>
            /// The w m_ ncmouseleave.
            /// </summary>
            WM_NCMOUSELEAVE = 0x2A2, 

            /// <summary>
            /// The w m_ ncmousemove.
            /// </summary>
            WM_NCMOUSEMOVE = 0xA0, 

            /// <summary>
            /// The w m_ ncpaint.
            /// </summary>
            WM_NCPAINT = 0x85, 

            /// <summary>
            /// The w m_ ncrbuttondblclk.
            /// </summary>
            WM_NCRBUTTONDBLCLK = 0xA6, 

            /// <summary>
            /// The w m_ ncrbuttondown.
            /// </summary>
            WM_NCRBUTTONDOWN = 0xA4, 

            /// <summary>
            /// The w m_ ncrbuttonup.
            /// </summary>
            WM_NCRBUTTONUP = 0xA5, 

            /// <summary>
            /// The w m_ nextdlgctl.
            /// </summary>
            WM_NEXTDLGCTL = 0x28, 

            /// <summary>
            /// The w m_ nextmenu.
            /// </summary>
            WM_NEXTMENU = 0x213, 

            /// <summary>
            /// The w m_ notify.
            /// </summary>
            WM_NOTIFY = 0x4E, 

            /// <summary>
            /// The w m_ notifyformat.
            /// </summary>
            WM_NOTIFYFORMAT = 0x55, 

            /// <summary>
            /// The w m_ null.
            /// </summary>
            WM_NULL = 0x0, 

            /// <summary>
            /// The w m_ paint.
            /// </summary>
            WM_PAINT = 0xF, 

            /// <summary>
            /// The w m_ paintclipboard.
            /// </summary>
            WM_PAINTCLIPBOARD = 0x309, 

            /// <summary>
            /// The w m_ painticon.
            /// </summary>
            WM_PAINTICON = 0x26, 

            /// <summary>
            /// The w m_ palettechanged.
            /// </summary>
            WM_PALETTECHANGED = 0x311, 

            /// <summary>
            /// The w m_ paletteischanging.
            /// </summary>
            WM_PALETTEISCHANGING = 0x310, 

            /// <summary>
            /// The w m_ parentnotify.
            /// </summary>
            WM_PARENTNOTIFY = 0x210, 

            /// <summary>
            /// The w m_ paste.
            /// </summary>
            WM_PASTE = 0x302, 

            /// <summary>
            /// The w m_ penwinfirst.
            /// </summary>
            WM_PENWINFIRST = 0x380, 

            /// <summary>
            /// The w m_ penwinlast.
            /// </summary>
            WM_PENWINLAST = 0x38F, 

            /// <summary>
            /// The w m_ power.
            /// </summary>
            WM_POWER = 0x48, 

            /// <summary>
            /// The w m_ print.
            /// </summary>
            WM_PRINT = 0x317, 

            /// <summary>
            /// The w m_ printclient.
            /// </summary>
            WM_PRINTCLIENT = 0x318, 

            /// <summary>
            /// The w m_ querydragicon.
            /// </summary>
            WM_QUERYDRAGICON = 0x37, 

            /// <summary>
            /// The w m_ queryendsession.
            /// </summary>
            WM_QUERYENDSESSION = 0x11, 

            /// <summary>
            /// The w m_ querynewpalette.
            /// </summary>
            WM_QUERYNEWPALETTE = 0x30F, 

            /// <summary>
            /// The w m_ queryopen.
            /// </summary>
            WM_QUERYOPEN = 0x13, 

            /// <summary>
            /// The w m_ queuesync.
            /// </summary>
            WM_QUEUESYNC = 0x23, 

            /// <summary>
            /// The w m_ quit.
            /// </summary>
            WM_QUIT = 0x12, 

            /// <summary>
            /// The w m_ rbuttondblclk.
            /// </summary>
            WM_RBUTTONDBLCLK = 0x206, 

            /// <summary>
            /// The w m_ rbuttondown.
            /// </summary>
            WM_RBUTTONDOWN = 0x204, 

            /// <summary>
            /// The w m_ rbuttonup.
            /// </summary>
            WM_RBUTTONUP = 0x205, 

            /// <summary>
            /// The w m_ renderallformats.
            /// </summary>
            WM_RENDERALLFORMATS = 0x306, 

            /// <summary>
            /// The w m_ renderformat.
            /// </summary>
            WM_RENDERFORMAT = 0x305, 

            /// <summary>
            /// The w m_ setcursor.
            /// </summary>
            WM_SETCURSOR = 0x20, 

            /// <summary>
            /// The w m_ setfocus.
            /// </summary>
            WM_SETFOCUS = 0x7, 

            /// <summary>
            /// The w m_ setfont.
            /// </summary>
            WM_SETFONT = 0x30, 

            /// <summary>
            /// The w m_ sethotkey.
            /// </summary>
            WM_SETHOTKEY = 0x32, 

            /// <summary>
            /// The w m_ seticon.
            /// </summary>
            WM_SETICON = 0x80, 

            /// <summary>
            /// The w m_ setredraw.
            /// </summary>
            WM_SETREDRAW = 0xB, 

            /// <summary>
            /// The w m_ settext.
            /// </summary>
            WM_SETTEXT = 0xC, 

            /// <summary>
            /// The w m_ settingchange.
            /// </summary>
            WM_SETTINGCHANGE = 0x1A, 

            /// <summary>
            /// The w m_ showwindow.
            /// </summary>
            WM_SHOWWINDOW = 0x18, 

            /// <summary>
            /// The w m_ size.
            /// </summary>
            WM_SIZE = 0x5, 

            /// <summary>
            /// The w m_ sizeclipboard.
            /// </summary>
            WM_SIZECLIPBOARD = 0x30B, 

            /// <summary>
            /// The w m_ sizing.
            /// </summary>
            WM_SIZING = 0x214, 

            /// <summary>
            /// The w m_ spoolerstatus.
            /// </summary>
            WM_SPOOLERSTATUS = 0x2A, 

            /// <summary>
            /// The w m_ stylechanged.
            /// </summary>
            WM_STYLECHANGED = 0x7D, 

            /// <summary>
            /// The w m_ stylechanging.
            /// </summary>
            WM_STYLECHANGING = 0x7C, 

            /// <summary>
            /// The w m_ syncpaint.
            /// </summary>
            WM_SYNCPAINT = 0x88, 

            /// <summary>
            /// The w m_ syschar.
            /// </summary>
            WM_SYSCHAR = 0x106, 

            /// <summary>
            /// The w m_ syscolorchange.
            /// </summary>
            WM_SYSCOLORCHANGE = 0x15, 

            /// <summary>
            /// The w m_ syscommand.
            /// </summary>
            WM_SYSCOMMAND = 0x112, 

            /// <summary>
            /// The w m_ sysdeadchar.
            /// </summary>
            WM_SYSDEADCHAR = 0x107, 

            /// <summary>
            /// The w m_ syskeydown.
            /// </summary>
            WM_SYSKEYDOWN = 0x104, 

            /// <summary>
            /// The w m_ syskeyup.
            /// </summary>
            WM_SYSKEYUP = 0x105, 

            /// <summary>
            /// The w m_ tcard.
            /// </summary>
            WM_TCARD = 0x52, 

            /// <summary>
            /// The w m_ timechange.
            /// </summary>
            WM_TIMECHANGE = 0x1E, 

            /// <summary>
            /// The w m_ timer.
            /// </summary>
            WM_TIMER = 0x113, 

            /// <summary>
            /// The w m_ undo.
            /// </summary>
            WM_UNDO = 0x304, 

            /// <summary>
            /// The w m_ uninitmenupopup.
            /// </summary>
            WM_UNINITMENUPOPUP = 0x125, 

            /// <summary>
            /// The w m_ user.
            /// </summary>
            WM_USER = 0x400, 

            /// <summary>
            /// The w m_ userchanged.
            /// </summary>
            WM_USERCHANGED = 0x54, 

            /// <summary>
            /// The w m_ vkeytoitem.
            /// </summary>
            WM_VKEYTOITEM = 0x2E, 

            /// <summary>
            /// The w m_ vscroll.
            /// </summary>
            WM_VSCROLL = 0x115, 

            /// <summary>
            /// The w m_ vscrollclipboard.
            /// </summary>
            WM_VSCROLLCLIPBOARD = 0x30A, 

            /// <summary>
            /// The w m_ windowposchanged.
            /// </summary>
            WM_WINDOWPOSCHANGED = 0x47, 

            /// <summary>
            /// The w m_ windowposchanging.
            /// </summary>
            WM_WINDOWPOSCHANGING = 0x46, 

            /// <summary>
            /// The w m_ wininichange.
            /// </summary>
            WM_WININICHANGE = 0x1A
        }

        #endregion Enums

        #region Public Properties

        /// <summary>
        ///     Returns the automation object for the web browser
        /// </summary>
        public object Application
        {
            get
            {
                return this.axIWebBrowser2.Application;
            }
        }

        #endregion Public Properties

        #region Methods

        /// <summary>
        /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.
        ///     Called by the control when the underlying ActiveX control is created.
        /// </summary>
        /// <param name="nativeActiveXObject">
        /// </param>
        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void AttachInterfaces(object nativeActiveXObject)
        {
            this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
            base.AttachInterfaces(nativeActiveXObject);
        }

        /// <summary>
        ///     This method will be called to give you a chance to create your own event sink
        /// </summary>
        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void CreateSink()
        {
            // Make sure to call the base public class or the normal events won't fire
            base.CreateSink();
            this.events = new WebBrowserExtendedEvents(this);
            this.cookie = new AxHost.ConnectionPointCookie(this.ActiveXInstance, this.events, typeof(UnsafeNativeMethods.DWebBrowserEvents2));
        }

        /// <summary>
        ///     This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.
        ///     Called by the control when the underlying ActiveX control is discarded.
        /// </summary>
        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void DetachInterfaces()
        {
            this.axIWebBrowser2 = null;
            base.DetachInterfaces();
        }

        /// <summary>
        ///     Detaches the event sink
        /// </summary>
        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void DetachSink()
        {
            if (null != this.cookie)
            {
                this.cookie.Disconnect();
                this.cookie = null;
            }
        }

        /// <summary>
        /// Raises the <see cref="DownloadComplete"/> event
        /// </summary>
        /// <param name="e">
        /// Empty <see cref="EventArgs"/>
        /// </param>
        protected virtual void OnDownloadComplete(EventArgs e)
        {
            if (this.DownloadComplete != null)
            {
                this.DownloadComplete(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="Downloading"/> event
        /// </summary>
        /// <param name="e">
        /// Empty <see cref="EventArgs"/>
        /// </param>
        /// <remarks>
        /// You could start an animation or a notification that downloading is starting
        /// </remarks>
        protected void OnDownloading(EventArgs e)
        {
            if (this.Downloading != null)
            {
                this.Downloading(this, e);
            }
        }

        /// <summary>
        ///     Raises the <see cref="Quit" /> event
        /// </summary>
        protected void OnQuit()
        {
            EventHandler h = this.Quit;
            if (null != h)
            {
                h(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Raises the <see cref="StartNavigate"/> event
        /// </summary>
        /// <param name="e">
        /// The e.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when BrowserExtendedNavigatingEventArgs is null
        /// </exception>
        protected void OnStartNavigate(BrowserExtendedNavigatingEventArgs e)
        {
            Guard.ArgumentNotNull(e, "e");
            if (this.StartNavigate != null)
            {
                this.StartNavigate(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="StartNewWindow"/> event
        /// </summary>
        /// <param name="e">
        /// The e.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when BrowserExtendedNavigatingEventArgs is null
        /// </exception>
        protected void OnStartNewWindow(BrowserExtendedNavigatingEventArgs e)
        {
            Guard.ArgumentNotNull(e, "e");

            if (this.StartNewWindow != null)
            {
                this.StartNewWindow(this, e);
            }
        }

        /// <summary>
        /// Overridden
        /// </summary>
        /// <param name="m">
        /// The <see cref="Message"/> send to this procedure
        /// </param>
        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == (int)WindowsMessages.WM_PARENTNOTIFY)
            {
                // int lp = m.LParam.ToInt32();
                int wp = m.WParam.ToInt32();

                int X = wp & 0xFFFF;

                // int Y = (wp >> 16) & 0xFFFF;
                if (X == (int)WindowsMessages.WM_DESTROY)
                {
                    this.OnQuit();
                }
            }

            base.WndProc(ref m);
        }

        #endregion Methods

        // This public class will capture events from the WebBrowser
        /// <summary>
        /// The web browser extended events.
        /// </summary>
        public class WebBrowserExtendedEvents : UnsafeNativeMethods.DWebBrowserEvents2
        {
            #region Fields

            /// <summary>
            /// The browser.
            /// </summary>
            private readonly ExtendedWebBrowser _browser;

            #endregion Fields

            #region Constructors and Finalizers

            /// <summary>
            /// Initializes a new instance of the <see cref="WebBrowserExtendedEvents"/> class.
            /// </summary>
            public WebBrowserExtendedEvents()
            {
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="WebBrowserExtendedEvents"/> class.
            /// </summary>
            /// <param name="browser">
            /// The browser.
            /// </param>
            public WebBrowserExtendedEvents(ExtendedWebBrowser browser)
            {
                this._browser = browser;
            }

            #endregion Constructors and Finalizers

            // Implement whichever events you wish
            #region Public Methods and Operators

            /// <summary>
            /// The before navigate 2.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            /// <param name="URL">
            /// The url.
            /// </param>
            /// <param name="flags">
            /// The flags.
            /// </param>
            /// <param name="targetFrameName">
            /// The target frame name.
            /// </param>
            /// <param name="postData">
            /// The post data.
            /// </param>
            /// <param name="headers">
            /// The headers.
            /// </param>
            /// <param name="cancel">
            /// The cancel.
            /// </param>
            public void BeforeNavigate2(object pDisp, ref object URL, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel)
            {
                var urlUri = new Uri(URL.ToString());

                string tFrame = null;
                if (targetFrameName != null)
                {
                    tFrame = targetFrameName.ToString();
                }

                var args = new BrowserExtendedNavigatingEventArgs(pDisp, urlUri, tFrame, UrlContext.None);
                this._browser.OnStartNavigate(args);

                cancel = args.Cancel;
                pDisp = args.AutomationObject;
            }

            /// <summary>
            /// The client to host window.
            /// </summary>
            /// <param name="CX">
            /// The cx.
            /// </param>
            /// <param name="CY">
            /// The cy.
            /// </param>
            public void ClientToHostWindow(ref int CX, ref int CY)
            {
            }

            /// <summary>
            /// The command state change.
            /// </summary>
            /// <param name="Command">
            /// The command.
            /// </param>
            /// <param name="Enable">
            /// The enable.
            /// </param>
            public void CommandStateChange(int Command, bool Enable)
            {
            }

            /// <summary>
            /// The document complete.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            /// <param name="URL">
            /// The url.
            /// </param>
            public void DocumentComplete(object pDisp, ref object URL)
            {
            }

            // Fired when downloading begins
            /// <summary>
            /// The download begin.
            /// </summary>
            public void DownloadBegin()
            {
                this._browser.OnDownloading(EventArgs.Empty);
            }

            // Fired when downloading is completed
            /// <summary>
            /// The download complete.
            /// </summary>
            public void DownloadComplete()
            {
                this._browser.OnDownloadComplete(EventArgs.Empty);
            }

            /// <summary>
            /// The file download.
            /// </summary>
            /// <param name="cancel">
            /// The cancel.
            /// </param>
            public void FileDownload(ref bool cancel)
            {
            }

            /// <summary>
            /// The navigate complete 2.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            /// <param name="URL">
            /// The url.
            /// </param>
            public void NavigateComplete2(object pDisp, ref object URL)
            {
            }

            /// <summary>
            /// The navigate error.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            /// <param name="URL">
            /// The url.
            /// </param>
            /// <param name="frame">
            /// The frame.
            /// </param>
            /// <param name="statusCode">
            /// The status code.
            /// </param>
            /// <param name="cancel">
            /// The cancel.
            /// </param>
            public void NavigateError(object pDisp, ref object URL, ref object frame, ref object statusCode, ref bool cancel)
            {
            }

            // The NewWindow2 event, used on Windows XP SP1 and below
            /// <summary>
            /// The new window 2.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            /// <param name="cancel">
            /// The cancel.
            /// </param>
            public void NewWindow2(ref object pDisp, ref bool cancel)
            {
                var args = new BrowserExtendedNavigatingEventArgs(pDisp, null, null, UrlContext.None);
                this._browser.OnStartNewWindow(args);
                cancel = args.Cancel;
                pDisp = args.AutomationObject;
            }

            // NewWindow3 event, used on Windows XP SP2 and higher
            /// <summary>
            /// The new window 3.
            /// </summary>
            /// <param name="ppDisp">
            /// The pp disp.
            /// </param>
            /// <param name="Cancel">
            /// The cancel.
            /// </param>
            /// <param name="dwFlags">
            /// The dw flags.
            /// </param>
            /// <param name="bstrUrlContext">
            /// The bstr url context.
            /// </param>
            /// <param name="bstrUrl">
            /// The bstr url.
            /// </param>
            public void NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl)
            {
                var args = new BrowserExtendedNavigatingEventArgs(ppDisp, new Uri(bstrUrl), null, (UrlContext)dwFlags);
                this._browser.OnStartNewWindow(args);
                Cancel = args.Cancel;
                ppDisp = args.AutomationObject;
            }

            /// <summary>
            /// The on full screen.
            /// </summary>
            /// <param name="fullScreen">
            /// The full screen.
            /// </param>
            public void OnFullScreen(bool fullScreen)
            {
            }

            /// <summary>
            /// The on menu bar.
            /// </summary>
            /// <param name="menuBar">
            /// The menu bar.
            /// </param>
            public void OnMenuBar(bool menuBar)
            {
            }

            /// <summary>
            /// The on quit.
            /// </summary>
            public void OnQuit()
            {
            }

            /// <summary>
            /// The on status bar.
            /// </summary>
            /// <param name="statusBar">
            /// The status bar.
            /// </param>
            public void OnStatusBar(bool statusBar)
            {
            }

            /// <summary>
            /// The on theater mode.
            /// </summary>
            /// <param name="theaterMode">
            /// The theater mode.
            /// </param>
            public void OnTheaterMode(bool theaterMode)
            {
            }

            /// <summary>
            /// The on tool bar.
            /// </summary>
            /// <param name="toolBar">
            /// The tool bar.
            /// </param>
            public void OnToolBar(bool toolBar)
            {
            }

            /// <summary>
            /// The on visible.
            /// </summary>
            /// <param name="visible">
            /// The visible.
            /// </param>
            public void OnVisible(bool visible)
            {
            }

            /// <summary>
            /// The print template instantiation.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            public void PrintTemplateInstantiation(object pDisp)
            {
            }

            /// <summary>
            /// The print template teardown.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            public void PrintTemplateTeardown(object pDisp)
            {
            }

            /// <summary>
            /// The privacy impacted state change.
            /// </summary>
            /// <param name="bImpacted">
            /// The b impacted.
            /// </param>
            public void PrivacyImpactedStateChange(bool bImpacted)
            {
            }

            /// <summary>
            /// The progress change.
            /// </summary>
            /// <param name="progress">
            /// The progress.
            /// </param>
            /// <param name="progressMax">
            /// The progress max.
            /// </param>
            public void ProgressChange(int progress, int progressMax)
            {
            }

            /// <summary>
            /// The property change.
            /// </summary>
            /// <param name="szProperty">
            /// The sz property.
            /// </param>
            public void PropertyChange(string szProperty)
            {
            }

            /// <summary>
            /// The set secure lock icon.
            /// </summary>
            /// <param name="secureLockIcon">
            /// The secure lock icon.
            /// </param>
            public void SetSecureLockIcon(int secureLockIcon)
            {
            }

            /// <summary>
            /// The status text change.
            /// </summary>
            /// <param name="text">
            /// The text.
            /// </param>
            public void StatusTextChange(string text)
            {
            }

            /// <summary>
            /// The title change.
            /// </summary>
            /// <param name="text">
            /// The text.
            /// </param>
            public void TitleChange(string text)
            {
            }

            /// <summary>
            /// The update page status.
            /// </summary>
            /// <param name="pDisp">
            /// The p disp.
            /// </param>
            /// <param name="nPage">
            /// The n page.
            /// </param>
            /// <param name="fDone">
            /// The f done.
            /// </param>
            public void UpdatePageStatus(object pDisp, ref object nPage, ref object fDone)
            {
            }

            // This event doesn't fire.
            /// <summary>
            /// The window closing.
            /// </summary>
            /// <param name="isChildWindow">
            /// The is child window.
            /// </param>
            /// <param name="cancel">
            /// The cancel.
            /// </param>
            [DispId(0x00000107)]
            public void WindowClosing(bool isChildWindow, ref bool cancel)
            {
            }

            /// <summary>
            /// The window set height.
            /// </summary>
            /// <param name="height">
            /// The height.
            /// </param>
            public void WindowSetHeight(int height)
            {
            }

            /// <summary>
            /// The window set left.
            /// </summary>
            /// <param name="left">
            /// The left.
            /// </param>
            public void WindowSetLeft(int left)
            {
            }

            /// <summary>
            /// The window set resizable.
            /// </summary>
            /// <param name="resizable">
            /// The resizable.
            /// </param>
            public void WindowSetResizable(bool resizable)
            {
            }

            /// <summary>
            /// The window set top.
            /// </summary>
            /// <param name="top">
            /// The top.
            /// </param>
            public void WindowSetTop(int top)
            {
            }

            /// <summary>
            /// The window set width.
            /// </summary>
            /// <param name="width">
            /// The width.
            /// </param>
            public void WindowSetWidth(int width)
            {
            }

            #endregion Public Methods and Operators
        }
    }
}
